home *** CD-ROM | disk | FTP | other *** search
-
- /*
- File: SplineLibrary.c
-
- Contains: graphics libraries - Spline generation routines
-
- Written by: Cary Clark, Georgiann Delaney, Michael Fairman, Dave Good, Robert Johnson, Keith McGreggor, Oliver Steele, David Van Brink, Chris Yerga
-
- Copyright: © 1995 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <3> 4/7/95 jtd changed 'fract' to 'Fract'
- <2> 1/9/95 JD changed 'boolean' to 'Boolean'
- <1> 1/9/95 JD First checked in.
- */
-
- #include <Memory.h>
- #include "GraphicsLibraries.h"
-
- enum { onCurvePoint, offCurvePoint };
-
- typedef struct
- { long count;
- unsigned long mask;
- long control;
- long *bits;
- gxPoint *points;
- } splineBuild;
-
- static void BeginSplineBuild(splineBuild *build, long *bits, gxPoint *points)
- {
- build->count = 0;
- build->mask = 0;
- build->control = 0;
- build->bits = bits;
- build->points = points;
- }
-
- static void EndSplineBuild(splineBuild *build)
- {
- if (build->mask) *build->bits = build->control;
- }
-
- static void AddPoint(splineBuild *build, gxPoint *add, Boolean offCurve)
- {
- *build->points++ = *add;
- if (build->mask == 0) build->mask = (-1UL >> 1) + 1;
- if (offCurve) build->control |= build->mask;
- if ((build->mask >>= 1) == 0)
- { *build->bits++ = build->control;
- build->control = 0;
- }
- ++build->count;
- }
-
- static void AddTangent(splineBuild *build, gxPoint *base, gxPoint *tangent, Fixed factor)
- {
- gxPoint control;
- control.x = base->x + FractMultiply(tangent->x, factor);
- control.y = base->y + FractMultiply(tangent->y, factor);
- AddPoint(build, &control, offCurvePoint);
- }
-
- gxShape MirrorSpline(long count, gxPoint *points, Fract slack, Boolean closed)
- {
- gxShape spline;
- gxPoint *mine, *next;
- Fixed prevLen, nextLen;
- gxPoint prevDir, nextDir;
- splineBuild build;
- long actIndex, estCount = 3 * count, estIndex = 2 + (estCount + 31 >> 5);
- long *storage = (long *)NewPtr(estIndex * sizeof(long) + estCount * sizeof(gxPoint));
-
- BeginSplineBuild(&build, storage + 2, (gxPoint *)(storage + estIndex));
-
- mine = next = points;
- if (closed) mine += count - 1;
- nextDir.x = next->x - mine->x;
- nextDir.y = next->y - mine->y;
- nextLen = Magnitude(nextDir.x, nextDir.y);
- if (nextLen)
- { nextDir.x = FractDivide(nextDir.x, nextLen);
- nextDir.y = FractDivide(nextDir.y, nextLen);
- }
-
- while (count--)
- { mine = next;
- if (count) ++next;
- else if (closed) next = points;
- prevLen = nextLen;
- if (prevLen) prevDir = nextDir;
- nextDir.x = next->x - mine->x;
- nextDir.y = next->y - mine->y;
- nextLen = Magnitude(nextDir.x, nextDir.y);
- if (nextLen)
- { nextDir.x = FractDivide(nextDir.x, nextLen);
- nextDir.y = FractDivide(nextDir.y, nextLen);
- if (prevLen && slack)
- { gxPoint tangent;
- tangent.x = (prevDir.x >> 1) + (nextDir.x >> 1) >> 1;
- tangent.y = (prevDir.y >> 1) + (nextDir.y >> 1) >> 1;
- AddTangent(&build, mine, &tangent, -FractMultiply(slack, prevLen));
- if (nextLen != prevLen) AddPoint(&build, mine, onCurvePoint);
- AddTangent(&build, mine, &tangent, FractMultiply(slack, nextLen));
- }
- else goto addThis;
- }
- else if (!closed && count == 0)
- addThis: AddPoint(&build, mine, onCurvePoint);
- }
-
- EndSplineBuild(&build);
-
- actIndex = 2 + (build.count + 31 >> 5);
- if (actIndex < estIndex)
- BlockMove(storage + estIndex, storage + actIndex, build.count * sizeof(gxPoint));
- storage[0] = 1;
- storage[1] = build.count;
- spline = GXNewPaths((gxPaths *)storage);
- if (closed) GXSetShapeFill(spline, gxClosedFrameFill);
- else GXSetShapeFill(spline, gxOpenFrameFill);
-
- DisposePtr((Ptr)storage);
- return spline;
- }
-